﻿/*
*********************************************************************************************************
*                                                uC/GUI
*                        Universal graphic software for embedded applications
*
*                       (c) Copyright 2002, Micrium Inc., Weston, FL
*                       (c) Copyright 2002, SEGGER Microcontroller Systeme GmbH
*
*              uC/GUI is protected by international copyright laws. Knowledge of the
*              source code may not be used to write a similar product. This file may
*              only be used in accordance with a license and should not be redistributed
*              in any way. We appreciate your understanding and fairness.
*
----------------------------------------------------------------------
File        : GUIDEMO.c
Purpose     : 多个demo例程
----------------------------------------------------------------------
*/

// **************************************************************************
// 头文件

#include <stddef.h>
#include <stdio.h>

#include "GUI.h"
#if GUI_WINSUPPORT
#include "PROGBAR.h"
#include "LISTBOX.h"
#include "FRAMEWIN.h"
#include "BUTTON.h"
#endif
#include "GUIDEMO.h"

// **************************************************************************
// 静态变量

#if GUI_WINSUPPORT
static BUTTON_Handle   _stopButton;         //!< 停止按钮
static BUTTON_Handle   _nextButton;         //!< 下一个按钮
static FRAMEWIN_Handle _infoFrameWin;       //!< 信息框架窗口
static FRAMEWIN_Handle _ctrlFrameWin;       //!< 控制框架窗口
#if GUIDEMO_LARGE
static FRAMEWIN_Handle _infoWin;        //!< 信息窗口
static FRAMEWIN_Handle _ctrlWin;        //!< 控制窗口
static const char* _sInfo;              //!< 信息窗口字符串
#endif
#endif

static int _iTest;          //!< Demo演示程序主步骤
static int _iTestMinor;     //!< Demo演示程序次要步骤
static char _CmdNext;
static const char* _sExplain;               //!< 信息窗口显示的说明信息字符串

//! \brief      获取数组元素数量
#define COUNT_OF(Obj) (sizeof(Obj)/sizeof(Obj[0]))

//! \brief demo例程函数表 
//! 按照该列表中保存的函数指针依次运行
typedef void fVoidVoid(void);
static fVoidVoid * _apfTest[] = {
  GUIDEMO_HardwareInfo,
  GUIDEMO_Speed,
  #if GUI_SUPPORT_MEMDEV
    GUIDEMO_Graph,
  #endif
  GUIDEMO_Bitmap,
  GUIDEMO_Cursor,
  GUIDEMO_ShowInternationalFonts,
  GUIDEMO_ShowColorBar,
  GUIDEMO_ShowColorList,
  // GUIDEMO_DemoLUT,
  GUIDEMO_DemoPolygon,
  GUIDEMO_Circle,
  GUIDEMO_ShowMemoryDevice,
  GUIDEMO_Automotive,
  GUIDEMO_Navigation,

  #if GUI_WINSUPPORT
    GUIDEMO_DemoProgBar,
    GUIDEMO_DemoFrameWin,
    GUIDEMO_Dialog,
    GUIDEMO_WM,
    #if GUI_SUPPORT_TOUCH
      GUIDEMO_Touch,
    #endif
  #endif
  0
};

// **************************************************************************
// 静态例程

//! \brief      更新控制窗口
//! \return     void
static void _UpdateCmdWin(void) {
#if GUI_WINSUPPORT && GUIDEMO_LARGE
    WM_InvalidateWindow(_ctrlWin);
#endif
}

//! \brief      控制窗口消息例程
//! \details    该函数为窗口的消息例程，所有消息都由该函数处理
//! \param[in]  pMsg   消息指针
//! \return     void
#if (GUI_WINSUPPORT && GUIDEMO_LARGE)
static void _cbCmdWin(WM_MESSAGE* pMsg) {
    switch (pMsg->MsgId) {
    case WM_PAINT:
        // 更新控制窗口信息
        GUI_SetBkColor(GUI_GRAY);
        GUI_Clear();
        char strbuff[16];
        snprintf(strbuff, sizeof(strbuff), "Demo %d.%d/%d", _iTest + 1,
            _iTestMinor, COUNT_OF(_apfTest));
        strbuff[15] = '\0';
        GUI_DispString(strbuff);
    default:
        WM_DefaultProc(pMsg);
    }
}
#endif

//! \brief      更新信息窗口
//! \details    调用该函数将刷新信息窗口的显示
//! \return     void
static void _UpdateInfoWin(void) {
#if GUI_WINSUPPORT && GUIDEMO_LARGE
    GUI_RECT rClient;
    WM_HWIN hWin;
    GUI_CONTEXT ContextOld;
    GUI_SaveContext(&ContextOld);
    // 更新信息窗口
    WM_ShowWindow(_infoWin);
    WM_ShowWindow(_infoFrameWin);
    hWin = WM_SelectWindow(_infoWin);
    GUI_GetClientRect(&rClient);
    GUI_SetBkColor(GUI_WHITE);
    GUI_Clear();
    // 显示信息字符串
    GUI_SetColor(GUI_BLACK);
    GUI_SetFont(&GUI_Font13_1);
    GUI_SetTextAlign(GUI_TA_HCENTER);
    GUI_DispStringHCenterAt(_sInfo, (rClient.x1 - rClient.x0) / 2, 0);
    // 显示详细信息字符串
    GUI_SetTextAlign(GUI_TA_LEFT);
    GUI_SetFont(&GUI_Font8_ASCII);
    GUI_DispStringAt(_sExplain, 0, 20);
    WM_SelectWindow(hWin);
    GUI_RestoreContext(&ContextOld);
#endif
}

// **************************************************************************
// 接口函数

//! \brief      设置背景色
//! \details    设置颜色时检查颜色的有效性，无效颜色将使用黑色代替
//! \param[in]  Color   设置的颜色
//! \return     当前设置的颜色
GUI_COLOR GUIDEMO_SetBkColor(GUI_COLOR Color) {
    GUI_COLOR r;
    if (GUI_ColorIsAvailable(GUI_RED)) {
        r = Color;
    }
    else {
        r = GUI_BLACK;
    }
    GUI_SetBkColor(r);
    return r;
}

//! \brief      设置前景色
//! \details    设置颜色时检查颜色的有效性，无效颜色将使用黑色代替
//! \param[in]  Color   设置的颜色
//! \return     当前设置的颜色
GUI_COLOR GUIDEMO_SetColor(GUI_COLOR Color) {
    GUI_COLOR r;
    if (GUI_ColorIsAvailable(GUI_RED)) {
        r = Color;
    }
    else {
        r = GUI_WHITE;
    }
    GUI_SetColor(r);
    return r;
}

//! \brief      延时函数
//! \details    调用该函数将延时一段时间，并且以进度条形式显示延时进度
//! \param[in]  t   延时时间
//! \return     void
void GUIDEMO_Delay(int t) {
#if GUI_WINSUPPORT
    int tm, value;
#if GUIDEMO_LARGE
    PROGBAR_Handle hProg;   //进度条句柄
#endif
    WM_SetForegroundWindow(_stopButton);
    //创建进度条控件
#if GUIDEMO_LARGE
    hProg = (t > 100) ? PROGBAR_CreateAsChild(10, 10, 60, 7, _ctrlWin, 0,
        WM_CF_SHOW | WM_CF_STAYONTOP | WM_CF_MEMDEV) : 0;
    PROGBAR_SetMinMax(hProg, 0, t);
#endif
    //延时并更新进度条
    tm = GUI_GetTime();
    do {
        value = GUI_GetTime() - tm;
#if GUIDEMO_LARGE
        PROGBAR_SetValue(hProg, value);
        WM_ExecIdle();
#endif
        GUI_Delay(10);
    } while ((value < t) && !GUIDEMO_CheckCancel());
    //清理并更新控制窗口
#if GUIDEMO_LARGE
    PROGBAR_Delete(hProg);
#endif
    _UpdateCmdWin();
    WM_ExecIdle();
#else
    GUI_Delay(t);
#endif
}

//! \brief      等待函数
//! \details    延时4秒钟并通知开始下一个步骤
//! \return     void
void GUIDEMO_Wait(void) {
    GUIDEMO_Delay(4000);
    GUIDEMO_NotifyStartNext();
}

//! \brief      检查取消案件是否按下
//! \return     
int GUIDEMO_CheckCancel(void) {
    int c = GUI_GetKey();
#if GUI_WINSUPPORT
    WM_ExecIdle();
#endif
    if ((c == 'n') || (c == 'N'))
        _CmdNext = 1;
    if ((c == 's') || (c == 'S')) {
        GUI_Delay(500);
        do {
            GUI_Delay(10);
#if GUI_WINSUPPORT
            WM_ExecIdle();
#endif
            c = GUI_GetKey();
        } while (!c);
    }
    return _CmdNext;
}

//! \brief      显示信息文字
//! \details    在信息窗口中显示说明信息
//! \param[in]  s   说明信息字符串
//! \return     void
void GUIDEMO_ShowInfo(const char* s) {
    // 设置字符串并更新信息窗口
    _sExplain = s;
    _UpdateInfoWin();
}

//! \brief      隐藏信息窗口
//! \details    调用该函数信息窗口将被隐藏显示
//! \return     void
void GUIDEMO_HideInfoWin(void) {
#if GUI_WINSUPPORT
    WM_HideWindow(_infoFrameWin);
#endif
}

//! \brief      函数简述(限制在一行)
//! \details    详细功能描述(可选)
//! \param[in]  argc   输入参数
//! \param[out] argv   输出参数
//! \return     返回值说明(无返回可省略该字段)
void GUIDEMO_NotifyStartNext(void) {
    _CmdNext = 0;
    _UpdateCmdWin();
    _iTestMinor++;
}

//! \brief      等待按键按下
//! \return     获取的按键值
int GUIDEMO_WaitKey(void) {
    int r = 0;
    int tMax = GUI_GetTime() + 4000;
    int tDiff;
#if GUI_WINSUPPORT
    PROGBAR_Handle hProg = PROGBAR_Create(LCD_GetXSize() - 70,
        LCD_GetYSize() - 40,
        80, 5, WM_CF_SHOW);
#endif
    while (tDiff = tMax - GUI_GetTime(), (tDiff > 0) && !GUIDEMO_CheckCancel()) {
        if ((r = GUI_GetKey()) != 0)
            break;
    }
#if GUI_WINSUPPORT
    PROGBAR_Delete(hProg);
    WM_ExecIdle();
#endif
    return r;
}

//! \brief      在信息窗口显示信息
//! \details    调用该函数可在信息窗显示简要信息和说明信息
//! \param[in]  s    简要信息字符串
//! \param[in]  sExp 说明信息字符串   
//! \return     void
void GUIDEMO_ShowIntro(const char * s, const char * sExp) {
    GUI_CONTEXT ContextOld;
    GUI_SaveContext(&ContextOld);
#if GUI_WINSUPPORT && GUIDEMO_LARGE
    _sInfo = s;
#endif
    _sExplain = sExp;
#if 0
    GUI_SetDefault();
    GUIDEMO_HideInfoWin();
    GUI_SetBkColor(GUI_BLUE);
    GUI_SetColor(GUI_WHITE);
    GUI_Clear();
    GUI_SetFont(&GUI_FontComic18B_ASCII);
    GUI_DispStringHCenterAt(s, LCD_GET_XSIZE() / 2, LCD_GET_YSIZE() / 3 - 10);
    if (_sExplain) {
        GUI_SetFont(&GUI_Font8_ASCII);
        GUI_DispStringHCenterAt(_sExplain, LCD_GET_XSIZE() / 2, LCD_GET_YSIZE() / 2 - 10);
    }
    GUIDEMO_Delay(_sExplain ? 2000 : 4000);
#endif
#if GUI_WINSUPPORT
    _UpdateInfoWin();
    _UpdateCmdWin();
#endif
    GUI_RestoreContext(&ContextOld);
#if GUI_WINSUPPORT
    WM_ExecIdle();
#endif
    GUIDEMO_NotifyStartNext();
    GUI_SetBkColor(GUI_RED);
    GUI_Clear();
}

//! \brief      GUI Demo演示程序主函数
//! \details    该函数创建整个演示程序框架并依次调用各个模块的演示函数
//! \return     void
#if GUIDEMO_LARGE
void GUIDEMO_main(void) {
#if GUI_WINSUPPORT
    int xSize, ySize, xPos, yPos;
    int buttonSizeX, buttonSizeY;
#endif
    // 清屏并创建启动停止控制按钮等
#if (GUI_SUPPORT_CURSOR|GUI_SUPPORT_TOUCH)
    GUI_CURSOR_Show();
#endif
    GUI_Clear();
#if GUI_WINSUPPORT
#if LCD_NUM_DISPLAYS > 1
    FRAMEWIN_CreateAsChild(10, 10, 100, 100, WM_GetDesktopWindowEx(1), "Display 1", NULL, WM_CF_SHOW);
    WM_SetDesktopColorEx(GUI_RED, 1);
    GUI_Delay(1000);
#endif
    WM_SetCreateFlags(WM_CF_MEMDEV);  //在所有窗口中自动使用内存设备
    //计算创建位置
    buttonSizeX = 30;
    buttonSizeY = 20;
    // 创建控制按钮
    _ctrlFrameWin = FRAMEWIN_Create("Control", NULL, WM_CF_SHOW | WM_CF_STAYONTOP,
        LCD_GetXSize() - 80, LCD_GetYSize() - 60, 80, 60);
    _ctrlWin = WM_CreateWindowAsChild(0, 0, 0, 0, WM_GetFirstChild(_ctrlFrameWin), WM_CF_SHOW | WM_CF_STAYONTOP, &_cbCmdWin, 0);
    _stopButton = BUTTON_CreateAsChild(4, 20, buttonSizeX, buttonSizeY, _ctrlWin,
        'S', WM_CF_SHOW | WM_CF_STAYONTOP | WM_CF_MEMDEV);
    _nextButton = BUTTON_CreateAsChild(40, 20, buttonSizeX, buttonSizeY, _ctrlWin,
        'N', WM_CF_SHOW | WM_CF_STAYONTOP | WM_CF_MEMDEV);
    BUTTON_SetText(_stopButton, "Stop");
    BUTTON_SetText(_nextButton, "Next");
    _UpdateCmdWin();
    WM_ExecIdle();
#endif
    // 显示信息
    GUIDEMO_Intro();
#if GUI_WINSUPPORT
    //计算信息显示窗口位置
    xSize = LCD_GetXSize() / 2;
    ySize = 65;
    xPos = LCD_GetXSize() - xSize;
    yPos = 0;
    // 创建信息窗口
    _infoFrameWin = FRAMEWIN_Create("uC/GUI Demo", NULL, WM_CF_STAYONTOP,
        xPos, yPos, xSize, ySize);
    //_infoWin = WM_GetFirstChild(_infoFrameWin);
    _infoWin = WM_CreateWindowAsChild(0, 0, 0, 0, WM_GetFirstChild(_infoFrameWin), WM_CF_SHOW | WM_CF_STAYONTOP, 0, 0);
    WM_ExecIdle();
#endif
    // 运行各个demo例程
    for (_iTest = 0; _apfTest[_iTest]; _iTest++) {
        GUI_CONTEXT ContextOld;
        GUI_SaveContext(&ContextOld);
        _iTestMinor = 0;
        _UpdateCmdWin();
        (*_apfTest[_iTest])();
        _CmdNext = 0;
        GUI_RestoreContext(&ContextOld);
    }
    // 清理
#if GUI_WINSUPPORT
    WM_DeleteWindow(_ctrlWin);
    WM_DeleteWindow(_infoWin);
    WM_DeleteWindow(_ctrlFrameWin);
    WM_DeleteWindow(_infoFrameWin);
#endif
}

#else /* GUIDEMO_LARGE */

/*********************************************************************
*
*       GUIDEMO_main(): Small version of the demo
*
**********************************************************************
*/
void GUIDEMO_main(void) {
#if GUI_WINSUPPORT
    int i;
#endif
#if GUI_WINSUPPORT
#if LCD_NUM_DISPLAYS > 1
    FRAMEWIN_CreateAsChild(10, 10, 100, 100, WM_GetDesktopWindowEx(1), "Display 1", NULL, WM_CF_SHOW);
    GUI_Delay(1000);
#endif
    WM_SetCreateFlags(WM_CF_MEMDEV);  /* Automatically use memory devices on all windows */
    _ButtonSizeX = 27;
    _ButtonSizeY = 14;
    _ahButton[0] = BUTTON_Create(LCD_GetXSize() - _ButtonSizeX * 2 - 5,
        LCD_GetYSize() - _ButtonSizeY - 3,
        _ButtonSizeX, _ButtonSizeY,
        'H', WM_CF_SHOW | WM_CF_STAYONTOP | WM_CF_MEMDEV);
    _ahButton[1] = BUTTON_Create(LCD_GetXSize() - _ButtonSizeX - 3,
        LCD_GetYSize() - _ButtonSizeY - 3,
        _ButtonSizeX, _ButtonSizeY,
        'N', WM_CF_SHOW | WM_CF_STAYONTOP | WM_CF_MEMDEV);
    BUTTON_SetFont(_ahButton[0], &GUI_Font8_ASCII);
    BUTTON_SetFont(_ahButton[1], &GUI_Font8_ASCII);
    BUTTON_SetText(_ahButton[0], "Stop");
    BUTTON_SetText(_ahButton[1], "Next");
    _UpdateCmdWin();
    WM_ExecIdle();
#endif
    /* Show Intro */
    GUIDEMO_Intro();
    /* Run the individual demos !  */
    for (_iTest = 0; _apfTest[_iTest]; _iTest++) {
        GUI_CONTEXT ContextOld;
        GUI_SaveContext(&ContextOld);
        _iTestMinor = 0;
        _UpdateCmdWin();
        (*_apfTest[_iTest])();
        _CmdNext = 0;
        GUI_RestoreContext(&ContextOld);
    }
    /* Cleanup */
#if GUI_WINSUPPORT
    for (i = 0; i < COUNT_OF(_ahButton); i++) {
        BUTTON_Delete(_ahButton[i]);
    }
#endif
}

#endif /* GUIDEMO_LARGE */

